home *** CD-ROM | disk | FTP | other *** search
/ Turnbull China Bikeride / Turnbull China Bikeride - Disc 2.iso / STUTTGART / LANG / C / LIB / UNIXLIB37B / !UnixLib37 / src / stdio / c / print < prev    next >
Text File  |  1996-11-09  |  20KB  |  1,083 lines

  1. /****************************************************************************
  2.  *
  3.  * $Source: /unixb/home/unixlib/source/unixlib37/src/stdio/c/RCS/print,v $
  4.  * $Date: 1996/10/30 21:59:00 $
  5.  * $Revision: 1.3 $
  6.  * $State: Rel $
  7.  * $Author: unixlib $
  8.  *
  9.  * $Log: print,v $
  10.  * Revision 1.3  1996/10/30 21:59:00  unixlib
  11.  * Massive changes made by Nick Burret and Peter Burwood.
  12.  *
  13.  * Revision 1.2  1996/05/06 09:01:34  unixlib
  14.  * Updates to sources made by Nick Burrett, Peter Burwood and Simon Callan.
  15.  * Saved for 3.7a release.
  16.  *
  17.  * Revision 1.1  1996/04/19 21:32:42  simon
  18.  * Initial revision
  19.  *
  20.  ***************************************************************************/
  21.  
  22. static const char rcs_id[] = "$Id: print,v 1.3 1996/10/30 21:59:00 unixlib Rel $";
  23.  
  24. /* Implements __printf(buf,format,argp) which is called by
  25.  * all printf() functions to perform formatted output. */
  26.  
  27. /* A conversion is of the form "%[flags][width][.prec][size]function".
  28.  * For full details RTFM for printf(3). */
  29.  
  30. #include <sys/syslib.h>
  31.  
  32. #include <stddef.h>
  33. #include <stdlib.h>
  34. #include <string.h>
  35. #include <ctype.h>
  36. #include <stdarg.h>
  37. #include <stdio.h>
  38. #include <float.h>
  39.  
  40. __STDIOLIB__
  41.  
  42. /* To avoid truncation PRBUFSIZ should be 256+.
  43.  * This library will *not* buffer overflow unless PRBUFSIZ < 4.
  44.  * ANSI requires at least 509 - 512 sounds sensible (SJC). */
  45.  
  46. #define PRBUFSIZ    4096
  47.  
  48.  
  49. /* The floating point functions are the most efficient they can be without
  50.  * resorting to assuming IEEE 'D' or some other internal representation. */
  51.  
  52. /* Unfortunately most software FP units are *inaccurate* - it
  53.  * is probably worth changing these constants for architectures
  54.  * with built in hardware FP units - make MAXPREC larger &
  55.  * FPERR smaller for higher quality. Note that MAXPREC = 16
  56.  * corresponds to the limits of IEEE Packed Decimal format. */
  57.  
  58. #define MAXPREC     16    /* max. decimal precision for %feEgG */
  59. #define FPERR        2*DBL_EPSILON    /* cutoff value for zero test */
  60.  
  61. /* It's probably best to leave POINT alone... It works. - WRONG */
  62.  
  63. #define POINT        DBL_EPSILON    /* offset to compensate for rounding errors */
  64.  
  65.  
  66. /* the prototypes for the output functions */
  67.  
  68. static char *__p_nout (char *, va_list *);
  69.  
  70. static char *__p_char (char *, va_list *);
  71. static char *__p_str (char *, va_list *);
  72. static char *__p_sdec (char *, va_list *);
  73. static char *__p_uoct (char *, va_list *);
  74. static char *__p_udec (char *, va_list *);
  75. static char *__p_uhex (char *, va_list *);
  76. static char *__p_ffix (char *, va_list *);
  77. static char *__p_fexp (char *, va_list *);
  78. static char *__p_fmin (char *, va_list *);
  79. static char *__p_ptr (char *, va_list *);
  80.  
  81.  
  82. /* the buffer __prpad has to be prior to __prbuf in memory -
  83.  * __prjust() avoids having to do any buffer copying by being
  84.  * able to back into the __prpad area from __prbuf */
  85.  
  86. static char __prpad[(PRBUFSIZ << 1) + 2];
  87. static char *__prbuf = __prpad + PRBUFSIZ + 1;
  88.  
  89.  
  90. /* __prebuf is set to the start of the output buffer passed to __printf() and
  91.  * is used by __p_nout() to calculate the number of characters output */
  92.  
  93. static char *__prebuf;
  94.  
  95.  
  96. #define P_FLAG0     0x0001    /* '-' */
  97. #define P_FLAG1     0x0002    /* '0' */
  98. #define P_FLAG2     0x0004    /* '+' */
  99. #define P_FLAG3     0x0008    /* ' ' */
  100. #define P_FLAG4     0x0010    /* '#' */
  101. #define P_FLAG5     0x0020    /* 'h' */
  102. #define P_FLAG6     0x0040    /* 'l' */
  103. #define P_FLAG7     0x0080    /* 'L' */
  104.  
  105. static int __prflag;
  106. static unsigned int __prwidth;    /* width */
  107. static int __prprec;        /* -1 = unspecified; precision */
  108. static char __prfc;        /* function character */
  109.  
  110. static signed char __prfnc[32] =    /* conversions */
  111. {
  112.   -1, -1,
  113.   1,                /* %c */
  114.   3,                /* %d */
  115.   9,                /* %eE */
  116.   8,                /* %f */
  117.   10,                /* %gG */
  118.   -1,
  119.   4,                /* %i */
  120.   -1, -1, -1, -1,
  121.   0,                /* %n */
  122.   5,                /* %o */
  123.   11,                /* %p */
  124.   -1, -1,
  125.   2,                /* %s */
  126.   -1,
  127.   6,                /* %u */
  128.   -1, -1,
  129.   7,                /* %xX */
  130.   -1, -1, -1, -1, -1, -1, -1, -1
  131. };
  132.  
  133. /* __prfn[] is the array of output functions called by __printf() -
  134.  * they return a pointer to the end of the string (which is *not*
  135.  * necessarily 0 terminated) */
  136.  
  137. static char *(*__prfn[]) (char *, va_list *) =
  138. {
  139.   __p_nout,            /* %n no. of characters output so far */
  140.     __p_char,            /* %c character */
  141.     __p_str,            /* %s string */
  142.     __p_sdec,            /* %d signed decimal */
  143.     __p_sdec,            /* %i signed decimal */
  144.     __p_uoct,            /* %o unsigned octal */
  145.     __p_udec,            /* %u unsigned decimal */
  146.     __p_uhex,            /* %xX unsigned hex */
  147.     __p_ffix,            /* %f fixed notation double */
  148.     __p_fexp,            /* %eE exponential notation double */
  149.     __p_fmin,            /* %gG minimised space notation double */
  150.     __p_ptr            /* %p unsigned hex value of pointer */
  151. };
  152.  
  153.  
  154. /* __printf() */
  155.  
  156. int
  157. __printf (char *buf, const char *format, va_list ap)
  158. {
  159.   register const char *s1 = format;
  160.   register char *s2 = buf;
  161.  
  162.   __prebuf = buf;        /* for __p_nout() */
  163.  
  164.   while (*s1)
  165.     {
  166.       if (*s1 != '%' || *++s1 == '%')    /* left to right evaluation */
  167.     {
  168.       *s2++ = *s1++;
  169.       continue;
  170.     }
  171.  
  172.       {                /* we now have a % conversion */
  173.     register int i;
  174.     char *s;
  175.  
  176. /* looking for "%[flags][width][.prec][size]function" */
  177.  
  178. /* set flags */
  179.  
  180.     __prflag = 0;
  181.       flag:
  182.     if (*s1 == '-')
  183.       {
  184.         __prflag |= P_FLAG0, s1++;
  185.         goto flag;
  186.       }
  187.     if (*s1 == '0')
  188.       {
  189.         __prflag |= P_FLAG1, s1++;
  190.         goto flag;
  191.       }
  192.     if (*s1 == '+')
  193.       {
  194.         __prflag |= P_FLAG2, s1++;
  195.         goto flag;
  196.       }
  197.     if (*s1 == ' ')
  198.       {
  199.         __prflag |= P_FLAG3, s1++;
  200.         goto flag;
  201.       }
  202.     if (*s1 == '#')
  203.       {
  204.         __prflag |= P_FLAG4, s1++;
  205.         goto flag;
  206.       }
  207.  
  208. /* set __prwidth */
  209.  
  210.     __prwidth = 0;
  211.     if (isdigit (*s1))
  212.       {
  213.         __prwidth = (unsigned int) strtoul (s1, &s, 0);
  214.         s1 = s;
  215.       }
  216.     else
  217.       {
  218.         if (*s1 == '*')
  219.           {
  220.         int tmpwidth;
  221.         tmpwidth = va_arg (ap, int);
  222.         if (tmpwidth < 0)
  223.           {
  224.             __prflag |= P_FLAG0;
  225.             tmpwidth = -tmpwidth;
  226.           }
  227.         __prwidth = tmpwidth;
  228.         s1++;
  229.           }
  230.       }
  231.     if (__prwidth > PRBUFSIZ)
  232.       __prwidth = PRBUFSIZ;
  233.  
  234. /* set __prprec */
  235.  
  236.     __prprec = -1;
  237.     if (*s1 == '.')
  238.       {
  239.         s1++;
  240.         if (isdigit (*s1))
  241.           {
  242.         __prprec = (int) strtol (s1, &s, 0);
  243.         s1 = s;
  244.           }
  245.         else
  246.           {
  247.         if (*s1 == '*')
  248.           {
  249.             __prprec = va_arg (ap, int);
  250.             s1++;
  251.           }
  252.           }
  253.       }
  254.  
  255. /* set size */
  256.  
  257.     if (*s1 == 'h')
  258.       __prflag |= P_FLAG5, s1++;
  259.     else if (*s1 == 'l')
  260.       __prflag |= P_FLAG6, s1++;
  261.     else if (*s1 == 'L')
  262.       __prflag |= P_FLAG7, s1++;
  263.  
  264. /* call appropriate output function */
  265.  
  266.     i = __prfnc[(_tolower (*s1) - 'a') & 31];
  267.  
  268.     if (i >= 0)
  269.       {
  270.         __prfc = *s1;
  271.         s2 = __funcall ((*__prfn[i]), (s2, (va_list *) (&ap)));
  272.       }
  273.  
  274.     s1++;
  275.       }
  276.     }
  277.  
  278.   *s2 = 0;
  279.  
  280.   return ((size_t) (s2 - buf));    /* number of characters output */
  281. }
  282.  
  283.  
  284. /* __prjust() */
  285.  
  286. /* __prjust() justifies the string at __prbuf according to __prwidth etc.
  287.  * it's argument is the *end* of the string at __prbuf - it returns the
  288.  * start of the justified string. */
  289.  
  290. static char *
  291. __prjust (register char *e)
  292. {
  293.   register char *s1, *s2;
  294.   register char p;
  295.  
  296.   s1 = __prbuf;
  297.  
  298.   p = (__prflag & P_FLAG1) ? '0' : ' ';
  299.  
  300.   if (__prflag & P_FLAG0)
  301.     {
  302.       s2 = s1 + __prwidth;
  303.       while (e < s2)
  304.     *e++ = ' ';
  305.       *e = 0;
  306.       return (s1);
  307.     }
  308.   else
  309.     {
  310.       if ((e -= __prwidth) < s1)
  311.     {
  312.       s2 = e;
  313.       while (e < s1)
  314.         *e++ = p;
  315.       return (s2);
  316.     }
  317.       return (s1);
  318.     }
  319. }
  320.  
  321. /* __prdec() */
  322.  
  323. /* __prdec() is a subroutine (called by __p_...() functions) that writes
  324.  * a decimal number <x> backwards from <e> towards <b>, digit by digit.
  325.    If pad is set true then numbers  0<=x<=9 are prefixed with a zero.
  326.    The pad is only needed by the exponential print functions to comply
  327.    with ANSI standards. */
  328.  
  329. static char *
  330. __prdec (register char *b, register char *e, register unsigned int x, int pad)
  331. {
  332.   *e = 0;
  333.   if (pad)
  334.     pad = (x <= 9) ? 1 : 0;
  335.  
  336.   do
  337.     {
  338.       *--e = (x % 10) + '0';
  339.       x /= 10;
  340.     }
  341.   while (x && e > b);
  342.   if (pad)
  343.     *--e = '0';
  344.  
  345.   return (e);
  346. }
  347.  
  348. /* __prexp() */
  349.  
  350. /* __prexp() normalises <x> to a number of the form n.nnnn...
  351.  * and stores the exponent in *<e> */
  352.  
  353. static double
  354. __prexp (register double x, register int *e)
  355. {
  356.   register int h;
  357.  
  358.   h = 0;
  359.  
  360.   if (x != 0)
  361.     {
  362.       if (x >= 10)
  363.     {
  364.       register double l = 0, m = 10;
  365.  
  366.       while (x >= m)
  367.         {
  368.           l = m, m *= 10;
  369.           h++;
  370.         }
  371.       if (l)
  372.         x /= l;
  373.     }
  374.       else
  375.     {
  376.       while (x < 1)
  377.         {
  378.           x *= 10;
  379.           h--;
  380.         }
  381.     }
  382.     }
  383.  
  384. /* x is now n.nnnn... */
  385.  
  386.   *e = h;
  387.   return (x);
  388. }
  389.  
  390.  
  391. /* __p_nout() */
  392.  
  393. static char *
  394. __p_nout (register char *s, register va_list * ap)    /* %n */
  395. {
  396.   if (__prflag & P_FLAG5)
  397.     *va_arg (*ap, short *) = (short) (s - __prebuf);
  398.   else if (__prflag & P_FLAG6)
  399.     *va_arg (*ap, long *) = (long) (s - __prebuf);
  400.   else
  401.     *va_arg (*ap, int *) = (int) (s - __prebuf);
  402.  
  403.   return (s);
  404. }
  405.  
  406. /* __p_char() */
  407.  
  408. static char *
  409. __p_char (register char *s, register va_list * ap)    /* %c */
  410. {
  411.   register char *b;
  412.  
  413.   if (!__prwidth)
  414.     *s++ = va_arg (*ap, char);
  415.   else
  416.     {
  417.       b = __prbuf;
  418.       *b++ = va_arg (*ap, char);
  419.       *b = 0;
  420.       b = __prjust (b);
  421.       while (*s = *b)
  422.     s++, b++;
  423.     }
  424.  
  425.   return (s);
  426. }
  427.  
  428. /* __p_str() */
  429.  
  430. static char *
  431. __p_str (register char *s, register va_list * ap)    /* %s */
  432. {
  433.   register char *_s;
  434.   register char *b, *e;
  435.   register int p;
  436.  
  437.   p = (__prprec < 0) ? PRBUFSIZ : __prprec;
  438.   if (p > PRBUFSIZ)
  439.     p = PRBUFSIZ;
  440.  
  441.   _s = va_arg (*ap, char *);
  442.  
  443. /* tolerance */
  444.  
  445.   if (!_s)
  446.     _s = __null;
  447.  
  448. /* fast output if no width specified */
  449.  
  450.   if (!__prwidth)
  451.     {
  452.       e = s + p;
  453.       while ((s < e) && (*s = *_s))
  454.     s++, _s++;
  455.       return (s);
  456.     }
  457.  
  458.   e = (b = __prbuf) + p;
  459.  
  460.   while (b < e && (*b = *_s))
  461.     b++, _s++;
  462.  
  463.   *b = 0;
  464.   b = __prjust (b);
  465.  
  466.   while (*s = *b)
  467.     s++, b++;
  468.  
  469.   return (s);
  470. }
  471.  
  472. /* __p_sdec() */
  473.  
  474. static char *
  475. __p_sdec (register char *s, register va_list * ap)    /* %d */
  476. {
  477.   register int x, n;
  478.   register char *b, *e;
  479.   register int p;
  480.  
  481.   p = (__prprec < 0) ? 0 : __prprec;
  482.   if (p > PRBUFSIZ - 2)
  483.     p = PRBUFSIZ - 2;
  484.  
  485.   if (__prflag & P_FLAG5)
  486.     n = (int) va_arg (*ap, short);
  487.   else if (__prflag & P_FLAG6)
  488.     n = (int) va_arg (*ap, long);
  489.   else
  490.     n = va_arg (*ap, int);
  491.  
  492.   x = (n < 0) ? (-n) : n;
  493.  
  494.   b = __prbuf;
  495.   e = b + PRBUFSIZ;
  496.  
  497.   if ((__prflag & P_FLAG2) || (n < 0))
  498.     *b++ = (n < 0) ? '-' : '+';
  499.   else if (__prflag & P_FLAG3)
  500.     *b++ = ' ';
  501.  
  502.   e = __prdec (b, e, (unsigned int) x, 0);
  503.  
  504.   if (p)
  505.     {
  506.       x = p - strlen (e);
  507.       while (x > 0)
  508.     {
  509.       *b++ = '0';
  510.       x--;
  511.     }
  512.     }
  513.  
  514.   while (*b = *e)
  515.     b++, e++;
  516.  
  517.   if (!__prwidth)
  518.     b = __prbuf;
  519.   else
  520.     b = __prjust (b);
  521.  
  522.   while (*s = *b)
  523.     s++, b++;
  524.  
  525.   return (s);
  526. }
  527.  
  528. /* __p_uoct() */
  529.  
  530. static char *
  531. __p_uoct (register char *s, register va_list * ap)    /* %o */
  532. {
  533.   register unsigned int x, n;
  534.   register char *b, *e;
  535.   register int p;
  536.  
  537.   p = (__prprec < 0) ? 0 : __prprec;
  538.   if (p > PRBUFSIZ - 3)
  539.     p = PRBUFSIZ - 3;
  540.  
  541.   if (__prflag & P_FLAG5)
  542.     n = (unsigned int) va_arg (*ap, unsigned short);
  543.   else if (__prflag & P_FLAG6)
  544.     n = (unsigned int) va_arg (*ap, unsigned long);
  545.   else
  546.     n = va_arg (*ap, unsigned int);
  547.  
  548.   x = n;
  549.  
  550.   b = __prbuf;
  551.   *(e = (b + PRBUFSIZ)) = 0;
  552.  
  553.   do
  554.     {
  555.       *--e = (x & 7) + '0';
  556.       x >>= 3;
  557.     }
  558.   while (b < e && x);
  559.  
  560.   if (__prflag & P_FLAG2)
  561.     *b++ = '+';
  562.   else if (__prflag & P_FLAG3)
  563.     *b++ = ' ';
  564.  
  565.   if (__prflag & P_FLAG4)
  566.     *b++ = '0';
  567.  
  568.   if (p)
  569.     {
  570.       x = p - strlen (e);
  571.       while (x > 0)
  572.     {
  573.       *b++ = '0';
  574.       x--;
  575.     }
  576.     }
  577.  
  578.   while (*b = *e)
  579.     b++, e++;
  580.  
  581.   if (!__prwidth)
  582.     b = __prbuf;
  583.   else
  584.     b = __prjust (b);
  585.  
  586.   while (*s = *b)
  587.     s++, b++;
  588.  
  589.   return (s);
  590. }
  591.  
  592. /* __p_udec() */
  593.  
  594. static char *
  595. __p_udec (register char *s, register va_list * ap)    /* %u */
  596. {
  597.   register unsigned int x, n;
  598.   register char *b, *e;
  599.   register int p;
  600.  
  601.   p = (__prprec < 0) ? 0 : __prprec;
  602.   if (p > PRBUFSIZ - 2)
  603.     p = PRBUFSIZ - 2;
  604.  
  605.   if (__prflag & P_FLAG5)
  606.     n = (unsigned int) va_arg (*ap, unsigned short);
  607.   else if (__prflag & P_FLAG6)
  608.     n = (unsigned int) va_arg (*ap, unsigned long);
  609.   else
  610.     n = va_arg (*ap, unsigned int);
  611.  
  612.   x = n;
  613.  
  614.   b = __prbuf;
  615.   e = b + PRBUFSIZ;
  616.  
  617.   if (__prflag & P_FLAG2)
  618.     *b++ = '+';
  619.   else if (__prflag & P_FLAG3)
  620.     *b++ = ' ';
  621.  
  622.   e = __prdec (b, e, x, 0);
  623.  
  624.   if (p)
  625.     {
  626.       x = p - strlen (e);
  627.       while (x > 0)
  628.     {
  629.       *b++ = '0';
  630.       x--;
  631.     }
  632.     }
  633.  
  634.   while (*b = *e)
  635.     b++, e++;
  636.  
  637.   if (!__prwidth)
  638.     b = __prbuf;
  639.   else
  640.     b = __prjust (b);
  641.  
  642.   while (*s = *b)
  643.     s++, b++;
  644.  
  645.   return (s);
  646. }
  647.  
  648. /* __p_uhex() */
  649.  
  650. static char *
  651. __p_uhex (register char *s, register va_list * ap)    /* %xX */
  652. {
  653.   register unsigned int x, n;
  654.   register char *b, *e;
  655.   register char *hex;
  656.   register int p;
  657.  
  658.   p = (__prprec < 0) ? 0 : __prprec;
  659.   if (p > PRBUFSIZ - 4)
  660.     p = PRBUFSIZ - 4;
  661.  
  662.   hex = (__prfc == 'X') ? "0123456789ABCDEF" : "0123456789abcdef";
  663.  
  664.   if (__prflag & P_FLAG5)
  665.     n = (unsigned int) va_arg (*ap, unsigned short);
  666.   else if (__prflag & P_FLAG6)
  667.     n = (unsigned int) va_arg (*ap, unsigned long);
  668.   else
  669.     n = va_arg (*ap, unsigned int);
  670.  
  671.   x = n;
  672.  
  673.   b = __prbuf;
  674.   *(e = (b + PRBUFSIZ)) = 0;
  675.  
  676.   do
  677.     {
  678.       *--e = hex[x & 15];
  679.       x >>= 4;
  680.     }
  681.   while (b < e && x);
  682.  
  683.   if (__prflag & P_FLAG2)
  684.     *b++ = '+';
  685.   else if (__prflag & P_FLAG3)
  686.     *b++ = ' ';
  687.  
  688.   if ((__prflag & P_FLAG4) && n)
  689.     {
  690.       *b++ = '0';
  691.       *b++ = 'x';
  692.     }
  693.  
  694.   if (p)
  695.     {
  696.       x = p - strlen (e);
  697.       while (x > 0)
  698.     {
  699.       *b++ = '0';
  700.       x--;
  701.     }
  702.     }
  703.  
  704.   while (*b = *e)
  705.     b++, e++;
  706.  
  707.   if (!__prwidth)
  708.     b = __prbuf;
  709.   else
  710.     b = __prjust (b);
  711.  
  712.   while (*s = *b)
  713.     s++, b++;
  714.  
  715.   return (s);
  716. }
  717.  
  718. /* __p_ffix() */
  719.  
  720. static char *
  721. __p_ffix (register char *s, register va_list * ap)    /* %f */
  722. {
  723.   const double point = POINT;
  724.   const double err = FPERR;
  725.   register double x, n, w;
  726.   register unsigned int i;
  727.   int h;
  728.   register int p, m;
  729.   register char *b, *e;
  730.  
  731.   if (__prflag & P_FLAG7)
  732.     n = (double) va_arg (*ap, long double);
  733.   else
  734.     n = va_arg (*ap, double);
  735.  
  736.   b = __prbuf;
  737.   e = b + PRBUFSIZ;
  738.   if ((__prflag & P_FLAG2) || (n < 0))
  739.     *b++ = (n < 0) ? '-' : '+';
  740.   else if (__prflag & P_FLAG3)
  741.     *b++ = ' ';
  742.  
  743.   x = (n < 0) ? (-n) : n;
  744.   x = __prexp (x, &h);
  745.   w = 1;
  746.   while (h < 0)
  747.     {
  748.       w *= 10;
  749.       h++;
  750.     }
  751.   x /= w;
  752.  
  753. /* integer part - ensure at least 1 digit */
  754.  
  755.   do
  756.     {
  757.       x = (x - (double) (i = (unsigned int) (x + point))) * 10;
  758.       *b++ = i + '0';
  759.       h--;
  760.     }
  761.   while (b < e && h >= 0 && x > err);
  762.   while (b < e && h >= 0)
  763.     {
  764.       *b++ = '0';
  765.       h--;
  766.     }
  767.  
  768.   m = (__prprec < 0) ? 6 : __prprec;
  769.   p = (m > MAXPREC) ? MAXPREC : m;
  770.   m -= p;
  771.  
  772. /* fractional part */
  773.  
  774.   if (p || (__prflag & P_FLAG4))
  775.     {
  776.       if (b < e)
  777.     *b++ = '.';
  778.  
  779.       while (b < e && p && x > err)
  780.     {
  781.       x = (x - (double) (i = (unsigned int) (x + point))) * 10;
  782.       *b++ = i + '0';
  783.       p--;
  784.     }
  785.  
  786.       while (p && b < e)
  787.     {
  788.       *b++ = '0';
  789.       p--;
  790.     }
  791.       while (m && b < e)
  792.     {
  793.       *b++ = '0';
  794.       m--;
  795.     }
  796.     }
  797.  
  798.   *b = 0;
  799.  
  800.   if (!__prwidth)
  801.     b = __prbuf;
  802.   else
  803.     b = __prjust (b);
  804.  
  805.   while (*s = *b)
  806.     s++, b++;
  807.  
  808.   return (s);
  809. }
  810.  
  811. /* __p_fexp() */
  812.  
  813. static char *
  814. __p_fexp (register char *s, register va_list * ap)    /* %eE */
  815. {
  816.   const double point = POINT;
  817.   const double err = FPERR;
  818.   register double x, n;
  819.   register unsigned int i;
  820.   int h;
  821.   register int p, m;
  822.   register char *b, *e;
  823.  
  824.   if (__prflag & P_FLAG7)
  825.     n = (double) va_arg (*ap, long double);
  826.   else
  827.     n = va_arg (*ap, double);
  828.  
  829.   b = __prbuf;
  830.   e = b + PRBUFSIZ;
  831.   if ((__prflag & P_FLAG2) || (n < 0))
  832.     *b++ = (n < 0) ? '-' : '+';
  833.   else if (__prflag & P_FLAG3)
  834.     *b++ = ' ';
  835.  
  836.   x = (n < 0) ? (-n) : n;
  837.   x = __prexp (x, &h);
  838.  
  839.   m = (__prprec < 0) ? 6 : __prprec;
  840.   p = (m > MAXPREC) ? MAXPREC : m;
  841.   m -= p;
  842.  
  843. /* 1 digit before decimal point */
  844.  
  845.   x = (x - (double) (i = (unsigned int) (x + point))) * 10;
  846.   *b++ = i + '0';
  847.  
  848. /* fractional part */
  849.  
  850.   if (p || (__prflag & P_FLAG4))
  851.     {
  852.       if (b < e)
  853.     *b++ = '.';
  854.  
  855.       while (b < e && p && x > err)
  856.     {
  857.       x = (x - (double) (i = (unsigned int) (x + point))) * 10;
  858.       *b++ = i + '0';
  859.       p--;
  860.     }
  861.  
  862.       while (p && b < e)
  863.     {
  864.       *b++ = '0';
  865.       p--;
  866.     }
  867.       while (m && b < e)
  868.     {
  869.       *b++ = '0';
  870.       m--;
  871.     }
  872.     }
  873.  
  874. /* exponent */
  875.  
  876.   if (b < e)
  877.     *b++ = __prfc;
  878.   if (b < e)
  879.     *b++ = (h < 0) ? '-' : '+';
  880.  
  881.   if (b < e)
  882.     e = __prdec (b, e, (h < 0) ? (unsigned int) (-h) : (unsigned int) h, 1);
  883.  
  884.   while (*b = *e)
  885.     b++, e++;
  886.  
  887.   if (!__prwidth)
  888.     b = __prbuf;
  889.   else
  890.     b = __prjust (b);
  891.  
  892.   while (*s = *b)
  893.     s++, b++;
  894.  
  895.   return (s);
  896. }
  897.  
  898. /* __p_fmin() */
  899.  
  900. static char *
  901. __p_fmin (register char *s, register va_list * ap)    /* %gG */
  902. {
  903.   const double point = POINT;
  904.   const double err = FPERR;
  905.   register double x, n, w;
  906.   register unsigned int i;
  907.   int h;
  908.   register int p, m;
  909.   register char *b, *e;
  910.  
  911.   if (__prflag & P_FLAG7)
  912.     n = (double) va_arg (*ap, long double);
  913.   else
  914.     n = va_arg (*ap, double);
  915.  
  916.   b = __prbuf;
  917.   e = b + PRBUFSIZ;
  918.   if ((__prflag & P_FLAG2) || (n < 0))
  919.     *b++ = (n < 0) ? '-' : '+';
  920.   else if (__prflag & P_FLAG3)
  921.     *b++ = ' ';
  922.  
  923. /* %gG count significant figures of precision, not decimal places.
  924.  * For %e we decrement the precision (for the digit before the decimal point).
  925.  * For %f we subtract the exponent from the precision. */
  926.  
  927.   m = (__prprec < 0) ? 6 : __prprec;
  928.   p = (m > MAXPREC) ? MAXPREC : m;
  929.   m -= p;
  930.  
  931.   x = (n < 0) ? (-n) : n;
  932.   x = __prexp (x, &h);
  933.  
  934. /* "The style used depends on the value converted; style %e will be used
  935.  * only if the exponent resulting from the conversion is less than -4 or
  936.  * greater than the precision." - ANSI X3J11 */
  937.  
  938.   if (h < -4 || h > p)        /* %e */
  939.     {
  940.       if (p)
  941.     p--;            /* just in case */
  942.  
  943. /* 1 digit before decimal point */
  944.  
  945.       x = (x - (double) (i = (unsigned int) (x + point))) * 10;
  946.       *b++ = i + '0';
  947.  
  948. /* fractional part */
  949.  
  950.       if (p || (__prflag & P_FLAG4))
  951.     {
  952.       if (b < e)
  953.         *b++ = '.';
  954.  
  955.       while (b < e && p && x > err)
  956.         {
  957.           x = (x - (double) (i = (unsigned int) (x + point))) * 10;
  958.           *b++ = i + '0';
  959.           p--;
  960.         }
  961.  
  962.       if (__prflag & P_FLAG4)
  963.         {
  964.           while (p && b < e)
  965.         {
  966.           *b++ = '0';
  967.           p--;
  968.         }
  969.           while (m && b < e)
  970.         {
  971.           *b++ = '0';
  972.           m--;
  973.         }
  974.         }
  975.       else if (b < e)    /* waste trailing 0s */
  976.         {
  977.           while (*--b == '0');
  978.           b++;
  979.           if (*--b != '.')
  980.         b++;
  981.         }
  982.     }
  983.  
  984. /* exponent */
  985.  
  986.       if (b < e)
  987.     *b++ = __prfc - ('g' - 'e');
  988.       if (b < e)
  989.     *b++ = (h < 0) ? '-' : '+';
  990.  
  991.       if (b < e)
  992.     e = __prdec (b, e, (h < 0) ? (unsigned int) (-h) : (unsigned int) h, 1);
  993.  
  994.       while (*b = *e)
  995.     b++, e++;
  996.     }
  997.   else
  998.     /* %f */
  999.     {
  1000.       w = 1;
  1001.       while (h < 0)
  1002.     {
  1003.       w *= 10;
  1004.       h++;
  1005.     }
  1006.       x /= w;
  1007.  
  1008.       p -= h;
  1009.  
  1010. /* integer part - ensure at least 1 digit */
  1011.  
  1012.       do
  1013.     {
  1014.       x = (x - (double) (i = (unsigned int) (x + point))) * 10;
  1015.       *b++ = i + '0';
  1016.       h--;
  1017.     }
  1018.       while (b < e && h >= 0 && x > err);
  1019.       while (b < e && h >= 0)
  1020.     {
  1021.       *b++ = '0';
  1022.       h--;
  1023.     }
  1024.  
  1025. /* fractional part */
  1026.  
  1027.       if (p || (__prflag & P_FLAG4))
  1028.     {
  1029.       if (b < e)
  1030.         *b++ = '.';
  1031.  
  1032.       while (b < e && p && x > err)
  1033.         {
  1034.           x = (x - (double) (i = (unsigned int) (x + point))) * 10;
  1035.           *b++ = i + '0';
  1036.           p--;
  1037.         }
  1038.  
  1039.       if (__prflag & P_FLAG4)
  1040.         {
  1041.           while (p && (b < e))
  1042.         {
  1043.           *b++ = '0';
  1044.           p--;
  1045.         }
  1046.           while (m && (b < e))
  1047.         {
  1048.           *b++ = '0';
  1049.           m--;
  1050.         }
  1051.         }
  1052.       else if (b < e)    /* waste trailing 0s */
  1053.         {
  1054.           while (*--b == '0');
  1055.           b++;
  1056.           if (*--b != '.')
  1057.         b++;
  1058.         }
  1059.     }
  1060.  
  1061.       *b = 0;
  1062.     }
  1063.  
  1064.   if (!__prwidth)
  1065.     b = __prbuf;
  1066.   else
  1067.     b = __prjust (b);
  1068.  
  1069.   while (*s = *b)
  1070.     s++, b++;
  1071.  
  1072.   return (s);
  1073. }
  1074.  
  1075. /* __p_ptr() */
  1076.  
  1077. static char *
  1078. __p_ptr (register char *s, register va_list * ap)    /* %p */
  1079. {
  1080.   __prflag |= P_FLAG4;
  1081.   return (__p_uhex (s, ap));
  1082. }
  1083.